home *** CD-ROM | disk | FTP | other *** search
- ; INT08.ASM - interrupt and sound handlers for VOC-IT.C
-
- ; Written by Phil Inch for Game Developers Magazine (issue 3).
- ; Contributed to the public domain. If you use this program
- ; or a derivation thereof in your own programs, please put in
- ; a credit for me and/or the magazine.
-
-
- .MODEL large
-
- timer_data EQU 40h
- timer_counter EQU 42h
- timer_control EQU 43h
- speaker_port EQU 61h
-
- .CODE
-
- PUBLIC _NewInt8Function
- PUBLIC _PlaySound
-
- ; This new interrupt 8 handler just signals an end-of-interrupt
-
- _NewInt8Function PROC far
- push ax
- mov al,20h
- out 20h,al
- pop ax
- iret
- _NewInt8Function ENDP
-
-
- ; The "PlaySound" routine does the actual work of playing the sound
-
- _PlaySound PROC far
- ARG data:DWORD, countdown:WORD, os:WORD
-
- ; Standard C stack frame prelude
- push bp
- mov bp,sp
-
- ; Save registers we'll be using
- push ax
- push cx
- push dx
- push ds
- push si
-
- ; Set up timer 2 to only expect 1 byte countdown values, and to only
- ; generate one pulse
- mov al,10010000b
- out timer_control,al
-
- ; Connect timer 2 to the speaker
- in al,speaker_port
- or al,03h
- out speaker_port,al
-
- ; Set timer 0 up with the specified playback frequency
- mov al,36h
- out timer_control,al
- mov cx,[countdown]
- mov al,cl
- out timer_data,al
- mov al,ch
- out timer_data,al
-
- ; Get the address of the sound sample
- lds si,[data]
- cld
- mov cx,[os]
-
- ; This is where the real work begins. First we'll "normalise" DS:SI so that
- ; SI < 16.
- normalise_si:
- cmp si,16
- jl play_loop
- sub si,16
- inc cx
- jmp normalise_si
-
- ; This is the main loop
- play_loop:
- hlt
-
- ; if we're oversampling, go straight to the routine that "plays" the byte
- loop oversample
-
- ; otherwise, retrieve the next byte of sample data
- mov cx,[os]
- lodsb
-
- ; if its FFh, that's the end of the sound so exit
- cmp al,0FFh
- je sound_finished
-
- oversample:
- ; send the byte to the timer
- out timer_counter,al
-
- ; update the pointer to the current sample byte. This method allows us
- ; to replay samples longer than 64k by modifing SI directly. (Every 16
- ; increments of SI is equal to one increment of DS).
- cmp si,16
- jl play_loop
- xor si,si
- mov bx,ds
- inc bx
- mov ds,bx
- jmp play_loop
-
- sound_finished:
- ; Set the timer back to its original settings (18.2Hz)
- mov al,00110110b
- out timer_control,al
- xor al,al
- out timer_data,al
- xor al,al
- out timer_data,al
-
- ; Set timer 2 back to its original settings
- mov al,10110110b
- out timer_control,al
-
- ; Disconnect timer 2 from the speaker
- in al,speaker_port
- and al,0FCh
- out speaker_port,al
-
- ; Restore registers and exit
- pop si
- pop ds
- pop dx
- pop cx
- pop ax
- pop bp
-
- retf
- _PlaySound ENDP
-
- END
-